C# async / await 用法 您所在的位置:网站首页 swift 方法要等待异步操作完成后才能返回该怎么做 C# async / await 用法

C# async / await 用法

2024-07-01 23:02| 来源: 网络整理| 查看: 265

目录

一、简介

二、异步等待返回结果

三、异步方法返回类型

四、await foreach

五、Task.Delay

结束

一、简介

await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。 异步操作完成后,await 运算符将返回操作的结果(如果有)。 当 await 运算符应用到表示已完成操作的操作数时,它将立即返回操作的结果,而不会暂停其所属的方法。 await 运算符不会阻止计算异步方法的线程。 当 await 运算符暂停其所属的异步方法时,控件将返回到方法的调用方。

二、异步等待返回结果

下面就演示 await 运算符常用的一些用法。

新建一个基于 .Net6 的 Winform 项目,界面就两个按钮,如下:

代码 

namespace 异步编程 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { IsTrue = false; AwaitEnd(); } private void button2_Click(object sender, EventArgs e) { IsTrue = true; } private bool IsTrue = false; private Task StartTimer() { var t = Task.Run(() => { while (true) { if (IsTrue) return "555"; Thread.Sleep(100); } }); return t; } private async void AwaitEnd() { Console.WriteLine("开始执行,时间:" + DateTime.Now.ToString()); var res = await StartTimer(); Console.WriteLine("结束:" + res + " 时间:" + DateTime.Now.ToString()); } } }

点击按钮1开始启动异步,点击按钮2,就返回结果,如果不点击按钮2,那么 while 循环就不会停止。

效果:

可以看到,点击了按钮1后,并不会让主线程卡死,窗体还是可以随意的拖动的,直到 StartTimer 方法将返回值返回回来后,才会继续执行后续的代码,这对一些需要阻塞线程,并获取另外的计算结果,然后才能继续计算的需求而言,有极大的帮助,比如读取数据库数据,如果网速比较慢,并且不会立刻就返回结果,用 await 运算符就可以在同一个方法里,等到获取到数据库返回结果后,再进行下一步运算,而不是从上到下,一下子就执行完了。

下面是以前我查询数据库写的代码,效果和上面演示中的 await 运算符是一样的,在下面的方法中,使用 Action 回调,代码都没写到一起,虽然逻辑一样,但用起来就不是那么的方便。

/// /// 执行SQL语句,并获取值 /// /// /// private static void ExecuteAndReturnValue(string sql, Action callBack) { Func Funcs = () => { DataSet dataSet = MySqlHelper.GetDataSet(sql); if (dataSet == null || dataSet.Tables.Count == 0) return null; return dataSet.Tables[0]; }; //执行任务 Task printRes = Task.Run(Funcs); //等待任务完成 printRes.GetAwaiter().OnCompleted(() => { if (callBack != null) callBack(printRes.Result); }); }

当前的示例,只是执行单个任务,如果有多个任务,用下面的方法也是可以的,

private Task DoSomethingAsync(int x) { return Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("值:" + x); }); } public async Task RunAsync() { foreach (var x in new[] { 1, 2, 3 }) { await DoSomethingAsync(x); } }

DoSomethingAsync 方法中,返回值可以从另一个数组中获取到 Task 并执行,我这里就不写那么仔细了,如果用面向过程的写法,就是这么写的:

private async void Test() { await Task.Run(async () => { await Task.Delay(4000); Trace.WriteLine("第1个线程执行"); }); await Task.Run(async () => { await Task.Delay(3000); Trace.WriteLine("第2个线程执行"); }); await Task.Run(async () => { await Task.Delay(2000); Trace.WriteLine("第3个线程执行"); }); }

三、异步方法返回类型

在方法里加上了 async 关键字后,返回值就只能使用固定的几个了,不然会报错。

异步函数的返回类型只能为: void、Task、Task、ValueTask 或 ValueTask

Task: 代表一个返回值T类型的操作。

Task: 代表一个无返回值的操作。

void: 为了和传统的事件处理程序兼容而设计。

四、await foreach

可以使用 await foreach 语句来使用异步数据流,即实现 IAsyncEnumerable 接口的集合类型。 异步检索下一个元素时,可能会挂起循环的每次迭代。

代码

private async void Test() { IAsyncEnumerable pullBasedAsyncSequence = ProduceAsyncSumSeqeunc(5); //开始另一项任务;用于使用异步数据序列! var consumingTask = Task.Run(() => ConsumeAsyncSumSeqeunc(pullBasedAsyncSequence)); await Task.Delay(TimeSpan.FromSeconds(3)); Console.WriteLine("搞一些其他事"); //只是为了演示!等待任务完成! await consumingTask; Console.WriteLine("异步流演示完成!" ); } private async Task ConsumeAsyncSumSeqeunc(IAsyncEnumerable sequence) { Console.WriteLine("执行 ConsumeAsyncSumSeqeunc 方法"); await foreach (var value in sequence) { Console.WriteLine($"value: {value}"); await Task.Delay(TimeSpan.FromSeconds(1)); }; } private async IAsyncEnumerable ProduceAsyncSumSeqeunc(int count) { Console.WriteLine("执行 ProduceAsyncSumSeqeunc 方法"); int index = 0; for (int i = 0; i < count; i++) { await Task.Delay(TimeSpan.FromSeconds(0.5)); yield return index += count; } }

调用 Test 方法后,即可打印

五、Task.Delay

解释:创建将在时间延迟后完成的任务。命名空间: System.Threading.Tasks

在上面的演示中用到了多次,例:

await Task.Delay(TimeSpan.FromSeconds(0.5));

在 Delay 方法中,可以用 TimeSpan 中的时、分、秒 表示

参考:

Delay(Int32)

创建一个在指定的毫秒数后完成的任务。

Delay(TimeSpan)

创建一个在指定的时间间隔后完成的任务。

Delay(Int32, CancellationToken)

创建一个在指定的毫秒数后完成的可取消任务。

Delay(TimeSpan, CancellationToken)

创建一个在指定的时间间隔后完成的可取消任务。

结束

如果这个帖子对你有所帮助,欢迎 关注 、点赞 、留言

end



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有